import axios, { AxiosError, type InternalAxiosRequestConfig } from "axios";
import type { AxiosRequestConfig, AxiosResponse } from "axios";
import { ElMessage } from "element-plus";
import { login, logout, refreshToken } from "./identityServer.config";
import { useUserInfoStore } from "@/stores/UserInfo";
import { useAxiosInfoStore } from "@/stores/AxiosInfo";

// 返回结果类型
export interface Result<T = any> {
	success: boolean;
	error: {
		detail: string;
		message: string;
	};
	sysSuccess: boolean;
	resultInfo: T;
	total?: number;
}

// 自定义配置
export interface AxiosCostomConfig {
	showLoading: boolean;
	showErrorMessage: boolean;
}

// 创建axios实例
const service = axios.create({
	baseURL: window.baseUrl,
	timeout: 300000,
	timeoutErrorMessage: "请求超时",
});

// 请求拦截
service.interceptors.request.use(
	async (config) => {
		if (!useUserInfoStore().token.access_token) {
			await login();
		}
		config.headers!["Authorization"] =
			"Bearer " + useUserInfoStore().token.access_token;
		return config;
	},
	(error) => {
		Promise.reject(error);
	}
);

// 响应拦截
service.interceptors.response.use(
	(response: AxiosResponse) => {
		let axiosStore = useAxiosInfoStore();
		let index = axiosStore.AllRequestList.findIndex(
			(item) =>
				// 通过config的url和method来判断是否是同一个请求
				item.config.url == response.config?.url &&
				item.config.method == response.config?.method
		);
		// 请求成功，清除掉请求列表中的请求
		index != -1 && axiosStore.AllRequestList.splice(index, 1);
		return response;
	},
	async (error: AxiosError) => {
		if (error.response?.status === 401) {
			// 未授权的请求统一放入store中,用于刷新token后重新发起请求
			let axiosStore = useAxiosInfoStore();
			error.config && axiosStore.unauthorizedRequest.push(error.config);
			let userStore = useUserInfoStore();
			// 刷新token,如果刷新token失败,则重新登录
			let token = await refreshToken(userStore.token.refresh_token);
			userStore.token = token;
			// 重新发起请求
			while (axiosStore.unauthorizedRequest.length > 0) {
				let config = axiosStore.unauthorizedRequest.shift()!;
				let index = axiosStore.AllRequestList.findIndex(
					(item) =>
						// 通过config的url和method来判断是否是同一个请求
						item.config.url == config?.url &&
						item.config.method == config?.method
				);
				// 如果customConfig存在，在数组中删除
				index != -1 && axiosStore.AllRequestList.splice(index, 1);
				await request(config, axiosStore.AllRequestList[index]?.customConfig);
			}
		}
		return error;
	}
);

/**
 * 请求入口
 * @param config axios配置
 * @param costomConfig 自定义配置
 * @returns
 */
const request = <T extends Result | Blob = Result>(
	config: AxiosRequestConfig,
	costomConfig?: AxiosCostomConfig
) => {
	// 自定义参数
	const costomConfigDefault = {
		showLoading: true,
		showErrorMessage: true,
	};
	// 默认参数填充
	costomConfig = Object.assign(costomConfigDefault, costomConfig);
	// 请求前保存自定义参数
	useAxiosInfoStore().AllRequestList.push({
		config: config as InternalAxiosRequestConfig,
		customConfig: costomConfig!,
	});
	return new Promise<T>((resolve, reject) => {
		service(config)
			.then((response: AxiosResponse<T>) => {
				if (config.responseType == "blob") {
					resolve(response.data);
				} else {
					let result = response.data as Result;
					if (result.success) {
						resolve(response.data);
					} else {
						if (costomConfig!.showErrorMessage) {
							ElMessage.error(result.error.message);
						}
						reject();
					}
				}
			})
			.catch((e: any) => {
				reject(e);
			});
	});
};

export default request;
